package com.zhaojun.cloud.common.util;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;

import java.util.*;

public class ListUtil extends CommonUtil {

	public static List<String> asStringList(List<Long> ids) {
		if (Detect.notEmpty(ids)) {
			List<String> strIds = new ArrayList<>();
			for (Long id : ids) {
				String strId = id == null ? "" : String.valueOf(id);
				strIds.add(strId);
			}
			return strIds;
		}
		return null;
	}

	public static List<Object> asObjectList(List<String> ids) {
		if (Detect.notEmpty(ids)) {
			List<Object> objs = new ArrayList<>();
			for (String id : ids) {
				objs.add(id);
			}
			return objs;
		}
		return null;
	}

	public static Long[] asLongArray(List<Long> list) {
		if (Detect.notEmpty(list)) {
			return list.toArray(new Long[list.size()]);
		}
		return null;
	}

	@SuppressWarnings("rawtypes")
	public static Long[] getLongArray(Map<String, Object> params, String key) {
		if (params.containsKey(key)) {
			List list = (List) params.get(key);
			if (Detect.notEmpty(list)) {
				Long[] arrs = new Long[list.size()];
				for (int i = 0; i < list.size(); i++) {
					arrs[i] = ObjectUtil.asLong(list.get(i));
				}
				return arrs;
			}
		}
		return null;
	}

	public static List<Long[]> grouping(Long[] values, int groupSize) {
		if (Detect.notEmpty(values)) {

			Assertion.isPositive(groupSize, "divideSize must be bigger than 0");

			int groupLength = values.length / groupSize + ((values.length % groupSize) > 0 ? 1 : 0);

			List<Long[]> longArryGroup = new LinkedList<>();
			Long[] valueArray = null;
			for (int i = 0; i < groupLength; i++) {
				int arrayLength = (i < groupLength - 1 || values.length % groupSize == 0) ? groupSize : (values.length % groupSize);

				valueArray = new Long[arrayLength];
				for (int j = 0; j < arrayLength; j++) {
					valueArray[j] = values[i * groupSize + j];
				}
				longArryGroup.add(valueArray);
			}

			return longArryGroup;
		}
		return null;
	}

	public static <T> List<List<T>> grouping(List<T> values, int groupSize) {
		if (CollectionUtils.isEmpty(values)) {
			return null;
		}
		AssertionEx.isPositive(groupSize, "divideSize must be bigger than 0");

		int size = values.size();
		int groupLength = size / groupSize + ((size % groupSize) > 0 ? 1 : 0);
		List<List<T>> longArryGroup = new LinkedList<>();
		for (int i = 0; i < groupLength; i++) {
			int arrayLength = (i < groupLength - 1 || size % groupSize == 0) ? groupSize : (size % groupSize);
			List<T> valueArray = new ArrayList<>();
			for (int j = 0; j < arrayLength; j++) {
				valueArray.add(values.get(i * groupSize + j));
			}
			longArryGroup.add(valueArray);
		}
		return longArryGroup;
	}

	/**
	 * Remove the duplicate element in List according to the specified keys in List bean and return a new list.</br>
	 * 
	 * If the parameters are empty or exception occurred, original list will be returned.
	 * 
	 * @param list
	 *            To be processed list
	 * @param fields
	 *            The fields in List bean as keys
	 * @return
	 */
	public static <E> List<E> escapeDuplication(List<E> list, String... fields) {
		if (CollectionUtils.isEmpty(list) || ArrayUtils.isEmpty(fields)) {
			return null;
		}

		for (String field : fields) {
			AssertionEx.notEmpty(field, "field not found, fields=" + ArrayUtils.toString(fields));
		}

		List<E> returnValue = new ArrayList<>();
		Set<String> keySet = new HashSet<>();

		for (E t : list) {
			StringBuffer hashCodeKey = new StringBuffer();
			for (String field : fields)
				try {
					hashCodeKey.append(BeanUtils.getProperty(t, field));
					hashCodeKey.append(DEFAULT_DELIMITER);
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
			if (!keySet.contains(hashCodeKey.toString())) {
				keySet.add(hashCodeKey.toString());
				returnValue.add(t);
			}
		}
		return returnValue;
	}

	public static Object[] asArray(List<?> list) {
		if (Detect.notEmpty(list)) {
			return list.toArray();
		}
		return null;
	}

	public static <E> List<E> escapeEmpty(List<E> list) {
		if (Detect.notEmpty(list)) {
			return list;
		}
		return null;
	}

	public static <E> List<E> safeList(List<E> list) {
		if (null == list) {
			list = new ArrayList<>();
		}
		return list;
	}

	public static <E> E firstOne(List<E> list) {
		if (Detect.notEmpty(list)) {
			return list.get(0);
		}
		return null;
	}

	public static <E> E lastOne(List<E> list) {
		if (Detect.notEmpty(list)) {
			return list.get(list.size() - 1);
		}
		return null;
	}

	public static <E> List<E> unmodifiableList(List<E> list) {
		if (Detect.notEmpty(list)) {
			return Collections.unmodifiableList(list);
		}
		return null;
	}


	public static Set<Long> longListToIdSet(List<Long> list) {
		Set<Long> set = new LinkedHashSet<>();
		if (Detect.notEmpty(list)) {
			for (Long t : list) {
				set.add(t);
			}
		}
		return set;
	}



	public static List<Long> distinctList(List<Long> list) {
		List<Long> newList = new ArrayList<>();
		if (Detect.notEmpty(list)) {
			for (Long id : list) {
				if (!newList.contains(id)) {
					newList.add(id);
				}
			}
		}
		return newList;
	}


	public static <E> boolean contains(E one, List<E> list) {
		if (Detect.notEmpty(list) && null != one) {
			for (E item : list) {
				if (one.equals(item)) {
					return true;
				}
			}
		}
		return false;
	}

}
